clear;
% 1.人脸数据集的导入与数据处理框架
reshaped_faces=[];
% 声明数据库名
database_name = "ORL";

% ORL5646
if (database_name == "ORL")
      row = 56;
column = 46;
people_num = 40;
pic_num_of_each = 10;
train_num_each = 5;% 每类训练数量
test_num_each = 5; % 每类测试数量
test_sum = test_num_each * people_num; % 测试总数
  for i=1:40    
    for j=1:10       
        if(i<10)
           a=imread(strcat('C:\Users\hp\Desktop\face\ORL56_46\orl',num2str(i),'_',num2str(j),'.bmp'));     
        else
            a=imread(strcat('C:\Users\hp\Desktop\face\ORL56_46\orl',num2str(i),'_',num2str(j),'.bmp'));  
        end
        a = double(a);
        a = mat2cell(a,[row/2,row/2],[column/2,column/2]);
        a1 = a{1};
        a2 = a{2};
        a3 = a{3};
        a4 = a{4};
        b1 = reshape(a1,row * column / 4,1);
        b1=double(b1);
        b2 = reshape(a2,row * column / 4,1);
        b2=double(b2);
        b3 = reshape(a3,row * column / 4,1);
        b3=double(b3);
        b4 = reshape(a4,row * column / 4,1);
        b4=double(b4);
        reshaped_faces=[reshaped_faces, b1,b2,b3,b4]; 
        
    end
  end

end

%AR5040
if (database_name == "AR")
    row = 50;
column = 40;
people_num = 40;
pic_num_of_each = 10;
train_num_each = 5;% 每类训练数量
test_num_each = 5; % 每类测试数量
test_sum = test_num_each * people_num; % 测试总数
    for i=1:40    
      for j=1:10       
        if(i<10)
           a=imread(strcat('C:\AR_Gray_50by40\AR00',num2str(i),'-',num2str(j),'.tif'));     
        else
            a=imread(strcat('C:\AR_Gray_50by40\AR0',num2str(i),'-',num2str(j),'.tif'));  
        end          
        a = double(a);
        a = mat2cell(a,[row/2,row/2],[column/2,column/2]);
        a1 = a{1};
        a2 = a{2};
        a3 = a{3};
        a4 = a{4};
        b1 = reshape(a1,row * column / 4,1);
        b1=double(b1);
        b2 = reshape(a2,row * column / 4,1);
        b2=double(b2);
        b3 = reshape(a3,row * column / 4,1);
        b3=double(b3);
        b4 = reshape(a4,row * column / 4,1);
        b4=double(b4);
        reshaped_faces=[reshaped_faces, b1,b2,b3,b4];   
      end
    end

end

%FERET_80
if (database_name == "FERET")
    row = 80;
column = 80;
people_num = 80;
pic_num_of_each = 7;
train_num_each = 4;% 每类训练数量
test_num_each = 3; % 每类测试数量
test_sum = test_num_each * people_num; % 测试总数
    for i=1:80    
      for j=1:7       
        a=imread(strcat('C:\Users\hp\Desktop\face\FERET_80\ff',num2str(i),'_',num2str(j),'.tif'));              
        a = mat2cell(a,[row/2,row/2],[column/2,column/2]);
        a1 = a{1};
        a2 = a{2};
        a3 = a{3};
        a4 = a{4};
        b1 = reshape(a1,row * column / 4,1);
        b1=double(b1);
        b2 = reshape(a2,row * column / 4,1);
        b2=double(b2);
        b3 = reshape(a3,row * column / 4,1);
        b3=double(b3);
        b4 = reshape(a4,row * column / 4,1);
        b4=double(b4);
        reshaped_faces=[reshaped_faces, b1,b2,b3,b4]; 
      end
    end

end
 

dimension = row * column;
count_right = 0;
num = 0; % 计数器
mindis = 999999;
for i = 0:1:people_num - 1
    totest_index = i + 1; %取出图片对应标签
    %对每一类进行一次线性回归
    for k = train_num_each * 4 + 1:1:pic_num_of_each * 4
       totest = reshaped_faces(:,i*pic_num_of_each * 4 + k); %取出每一待识别（分类）人脸
       num = num + 1;
       distest = []; %记录距离
     for j = 0:1:people_num - 1
       batch_faces = reshaped_faces(:,j * pic_num_of_each * 4 + 1 :j * pic_num_of_each * 4 + pic_num_of_each * 4); %取出每一类图片
       % 划分训练集与测试集
       %第一次  batch中的前train_num_each个数据作为训练集 后面数据作为测试集合
       train_data = batch_faces(:,1:train_num_each * 4);
       test_data = batch_faces(:,train_num_each * 4 + 1:pic_num_of_each * 4);
        % 1.线性回归
      w = inv(train_data' * train_data) * train_data' * totest;
       img_predict = train_data * w; % 计算预测图片

         % 2.岭回归
%        rr_data = (train_data' * train_data) + eye(train_num_each)*10^-6;
%        w = inv(rr_data) * train_data' * totest;
%        img_predict = train_data * w; % 计算预测图片

         % 3.lasso
%          [B,FitInfo] = lasso(train_data , totest);
%          img_predict = train_data * B + FitInfo.Intercept;

         % 4.权重线性回归
%        W = eye(dimension);
%        kk = 10^-1;
%            for jj = 1:1:dimension
%               diff_data = reshaped_faces(j+1,:) - reshaped_faces(jj,:);
%               W(jj,jj) = exp((diff_data * diff_data')/(-2.0 * kk^2));
%            end
%            w = pinv(train_data' * W * train_data) * train_data' * W * totest;
           
       % show_face(img_predict,row,column); %预测人脸展示
       dis = img_predict - totest; % 计算误差
       
       % 交叉验证
       %第二次  batch中的前五个数据 作为测试集合 后五个数据作为训练集
%        test_data = batch_faces(:,1:train_num_each);
%        train_data = batch_faces(:,train_num_each + 1:pic_num_of_each);
%        w = inv(train_data' * train_data) * train_data' * totest;
%        img_predict2 = train_data * w; % 计算预测图片
%        dis = (img_predict + img_predict2) / 2 - totest;

       distest = [distest,norm(dis)]; %计算欧氏距离
     % 取出误差最小的预测图片 并找到他对应的标签 作为预测结果输出
     end
            [min_dis,label_index] = min(distest); % 找到最小欧氏距离下标（预测类）
            if min_dis < mindis
               mindis = min_dis;
               label_predict = label_index;
            end
            if num == 4
                num = 0;
                mindis = 999999;
            if label_predict == totest_index
              count_right = count_right + 1;
            else  
                fprintf("预测错误：%d\n" ,(i + 1) * (k - train_num_each));
            end
            end
    end
         
end
recognition_rate = count_right / test_sum; 

% 输入向量，显示脸
function fig = show_face(vector, row, column)
    fig = imshow(mat2gray(reshape(vector, [row, column])));
end
    

